/*********************************************************************************
 * Copyright (C) 2022-present ISCAS & CESI.
 * PUACleaner is licensed under MulanPSL-2.0.
 * You can use this software according to the terms and conditions of the MulanPSL-2.0.
 * You may obtain a copy of MulanPSL-2.0 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the MulanPSL-2.0 for more details.
 *********************************************************************************/

package cn.puacleaner;

import java.io.*;
import java.util.HashMap;

public class PuaCleaner {

    final static int N_SAFE_FACTOR = 12;
    final static int ERR_SUCCESS = 0;
    final static int ERR_FAIL = 1;
    final static int SURROGATE_LEAD_START = 0xD800;
    final static int SURROGATE_LEAD_END = 0xDBFF;
    final static int SURROGATE_TAIL_START = 0xDC00;
    final static int SURROGATE_TAIL_END = 0xDFFF;
    private HashMap< String, String> mapPuaToUnicode = new HashMap< String, String>();

    public PuaCleaner(){

    }

    public void loadMapTable(){

    }

    public void addMapEntry(String puaChar, String unicodeChar){
        mapPuaToUnicode.put(puaChar, unicodeChar);
    }

    protected void loadMapTableFromTextFile(String pathName, String delimiter){
        String customDelimiter = delimiter;

        InputStreamReader reader = null;
        try{
            InputStream stream = new FileInputStream(pathName);
            reader = new InputStreamReader(stream, "utf-8");
            BufferedReader br = new BufferedReader(reader);
            String noteMark = "#";
            String line;
            while ((line = br.readLine()) != null){
                line = line.trim();
                if(line.contains(noteMark)){
                    line = line.substring(line.indexOf(noteMark));
                }
                String[] values = line.split(customDelimiter);
                if( values.length == 2){
                    String pua = values[1];
                    String unicode = values[2];
                    addMapEntry(pua, unicode);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    protected void loadMapTableFromInputStream(InputStream stream, String delimiter){
        String customDelimiter = delimiter;
        try {
            InputStreamReader reader = new InputStreamReader(stream, "utf-8");
            BufferedReader br = new BufferedReader(reader);
            String noteMark = "#";
            String line;
            while ((line = br.readLine()) != null){
                line = line.trim();
                if(line.indexOf(noteMark) >= 0){
                    line = line.substring(line.indexOf(noteMark));
                }
                String[] values = line.split(customDelimiter);
                if( values.length >= 2){
                    int l = values.length;
                    String pua = values[1];
                    String unicode = values[2];
                    addMapEntry(pua, unicode);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public String GetCleanText(String text){
        StringBuffer buf = new StringBuffer();
        int nLen = text.length();
        for(int i=0; i<nLen; i++){
            String strCurrentChar = "";
            int codepoint = text.codePointAt(i);
            if(codepoint >= SURROGATE_LEAD_START && codepoint <= SURROGATE_LEAD_END){
                strCurrentChar = text.substring(i, i+2);
                i += 1;
            }else {
                strCurrentChar = text.substring(i, i+1);
            }
            if(mapPuaToUnicode.containsKey(strCurrentChar)){
                String stdChar = (String) mapPuaToUnicode.get(strCurrentChar);
                buf.append(stdChar);
            }else {
                buf.append(strCurrentChar);
            }
        }
        return buf.toString();
    }


    public void cleanTextFile(String strInputFileName, String strOutputFileName) {
        int count = 0;
        InputStreamReader reader = null;
        OutputStreamWriter writer = null;
        try{
            InputStream stream = new FileInputStream(strInputFileName);
            reader = new InputStreamReader(stream, "utf-8");
            BufferedReader br = new BufferedReader(reader);
            OutputStream out_stream = new FileOutputStream(strOutputFileName);
            writer = new OutputStreamWriter(out_stream, "utf-8");
            BufferedWriter bw = new BufferedWriter(writer);

            String line;
            while ((line = br.readLine()) != null){
                String out_line = GetCleanText(line);
                out_line += System.getProperty("line.separator");
                bw.write(out_line);
                count ++;
                if(count == 996){
                    int a = 0;
                }
            }
            bw.flush();
            System.out.printf("Total lines: %d\n", count);
        } catch (Exception ex){
            System.out.printf("Error on processing file: %s\n", ex.getMessage());
        }finally {
            if(writer != null){
                try{
                    writer.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }
}
